package com.avr.externalComm.bluetooth
{
	import flash.events.StatusEvent;
	import flash.net.LocalConnection;	
	import org.osflash.signals.Signal;
	/**
	 * FlashBluetooth works using LocalConnection to communicate with BluecoveAIR application which sends commands to Java	  
	 * @author bioRex21
	 */
	public class FlashBluetooth 
	{
		/**
		 * Event that notifies when the device search has finished
		 */
		public var onSearchComplete:Signal;
		
		/**
		 * Event that notifies when a file has successfully sent
		 */
		public var onSendFileComplete:Signal;
		
		/**
		 * Event that notifies whe the Native Process has started again
		 */
		public var onRebootComplete:Signal;
		
		/**
		 * Event that notifies when a devices(s) is (are) found during search time
		 */
		public var onDeviceFound:Signal;
		
		/**
		 * Event that notifies when a file is being transfered(when there were no connection problems like sendFileErrors) 
		 * you can use this event to know when to play a transfering-data-like animation 
		 */
		public var onSendingFile:Signal;
		
		/**
		 * Event that notifies when an error ocurred when trying to send a file to target device.
		 * Handler function must be set to receive a String parameter (error description)
		 */
		public var onSendFileError:Signal;
		
		/**
		 * Event that notifies when an error has ocurred while trying to search bluetooth devices
		 * Handler function must be set to receive a String parameter (error description)
		 */
		public var onSearchError:Signal;
		
		/**
		 * Event that notifies a pairing fail due an incorrect PIN entered in target device
		 * (PIN is set to 0000 (four zeros, you can change this in the Java code))
		 */
		public var onWrongPin:Signal;
		
		/**
		 * Event that notifies that there has been an error while trying to communicate with BluecoveAIR
		 */
		public var onLocalConnectionError:Signal;
		
		
		
		private var _bridge:LocalConnection;
		private var _sendingConnectionName:String;
		private var _receiverConnectionName:String;
		
		
		/**
		 * Constructor
		 * @param	sendingConnectionName Connection string used by LocalConnection to send commands to BluecoveAIR
		 * @param	receiverConnectionName Connection string used by LocalConnection to receive data from BluecoveAIR
		 */
		public function FlashBluetooth(sendingConnectionName:String = "fromFlashApp", receiverConnectionName:String = "fromBluecoveAIR") 
		{
			onRebootComplete = new Signal();
			onSendFileComplete = new Signal();
			onSearchComplete = new Signal();
			onRebootComplete = new Signal();
			onDeviceFound = new Signal(Array);
			
			onSendingFile = new Signal();
			
			onSendFileError = new Signal(String);
			onSearchError = new Signal(String);
			onWrongPin = new Signal();
			
			
			_sendingConnectionName = "app#BluecoveAIR:" + sendingConnectionName;
			_receiverConnectionName = receiverConnectionName;
			
			
			
			_bridge = new LocalConnection();
			_bridge.allowDomain("*");
			_bridge.client = this;
			_bridge.addEventListener(StatusEvent.STATUS, onLCStatus);
			_bridge.connect(_receiverConnectionName);
		}
		
		
		//----- BLUETOOTH TASKS -----//
		
		/**
		 * Start looking for Bluetooth enabled devices, those devices's bluetooth must be as "visible"
		 * (not just activated)
		 */
		public function searchDevices():void 
		{
			
			_bridge.send(_sendingConnectionName, "searchDevices");
			
		}
		
		/**
		 * Sends a file to target device, currently supported files are .jpeg/.jpg, .3g2(video), and .mp3
		 * to extend this, also modify Java code
		 * @param	targetDeviceAddress
		 * @param	fileURL
		 */
		public function sendFile(targetDeviceAddress:String, fileURL:String):void 
		{
			if(fileURL.indexOf(".jpeg") != -1 || fileURL.indexOf(".jpg") != -1)
				_bridge.send(_sendingConnectionName, "sendFile", targetDeviceAddress, fileURL, "image");
					
			else if (fileURL.indexOf(".3g2") != -1)
				_bridge.send(_sendingConnectionName, "sendFile", targetDeviceAddress, fileURL, "video");
					
			else if (fileURL.indexOf(".mp3") != -1)
				_bridge.send(_sendingConnectionName, "sendFile", targetDeviceAddress, fileURL, "audio");
				
					
					
			else
				onSendFileError.dispatch("image file must have .jpeg, .3g2 or .mp3 extension");			
		}
		
		
		
		/**
		 * Stops native process and starts it again
		 * (I use it when a communication with target device has problems, and then try again)
		 * @param	time seconds you want the reboot to take
		 */
		public function reboot(time:Number = 4):void 
		{
			_bridge.send(_sendingConnectionName, "reboot", time.toString());
		}
		
		
		//----- THE FOLLOWING BLUETOOTH METHODS ARE CALLED FROM AIR APP ----//
		
		//----- ON BLUETOOTH EVENTS DISPATCHING -----//		
		
		/**
		 * Function called from AIR app that triggers onSearchComplete event
		 */
		public function triggerSearchComplete():void 
		{		
			onSearchComplete.dispatch();
		}
		
		/**
		 * Function called from BluecoveAIR that triggers onDeviceFound event
		 * @param	devices A single string containing devices found, this string is converted into an array automatically
		 */
		public function triggerDeviceDiscovered(mixedDevices:String):void 
		{
			var devicesArray:Array = getDevicesArrayFromMixedData(mixedDevices);
			
			onDeviceFound.dispatch(devicesArray);
		}
		
		/**
		 * Function called from BluecoveAIR that triggers onSendingFile event		 
		 */
		public function triggerSendingFile():void 
		{
			onSendingFile.dispatch();
		}
		
		/**
		 * Function called from BluecoveAIR that triggers onSendFileComplete event
		 */
		public function triggerSendFileComplete():void 
		{
			onSendFileComplete.dispatch();
		}
		
		/**
		 * Function called from BluecoveAIR that triggers onRebootComplete event
		 */
		public function triggerRebootComplete():void 
		{
			onRebootComplete.dispatch();
		}	
		
		
		//----- ON BLUETOOTH ERROR	EVENTS -----//
		
		/**
		 * Function called from BluecoveAIR that triggers onSendFileError event
		 * @param	errorMsg error description
		 */
		public function triggerSendFileError(errorMsg:String):void 
		{
			onSendFileError.dispatch(errorMsg);
		}
		
		/**
		 * Function called from BluecoveAIR that triggers onSearchError event
		 * @param	errorMsg error description
		 */
		public function triggerSearchError(errorMsg:String):void 
		{
			onSearchError.dispatch(errorMsg);
		}
		
		/**
		 * Function called from BluecoveAIR that triggers onWrongPin event
		 */
		public function triggerPinError():void 
		{
			onWrongPin.dispatch();
		}
		
		//-- LOCAL CONNECTION --//
		
		private function onLCStatus(event:StatusEvent):void 
		{
			
			switch (event.level) 
			{
				case "status":
				trace("LocalConnection.send() succeeded");
				break;
				
				case "error":
				trace("LocalConnection.send() failed");
				break;
			}
		}
		
		
		//----- UTILS -----//
		
		private function getDevicesArrayFromMixedData(mixedData:String):Array 
		{
			var formatedData:Array = [];
			
			var separatedDevices:Array = [];
			
			separatedDevices = mixedData.split("_onDeviceDiscoveredEnd_");
			//array traces: YO_address_001DBEE4AB7D, otherDevice_address_03143654, someOther_address_02132537
			
			var len:Number = separatedDevices.length-1;//last one is just a blank string (for using mixedData.split)
			
			for (var i:int = 0; i < len; i++) 
			{
				var nameAndAddress:Array = separatedDevices[i].split("_address_");
				
				var phoneData:BluetoothDeviceData = new BluetoothDeviceData(nameAndAddress[0], nameAndAddress[1]);
				formatedData.push(phoneData);
			}
			
			
			
			return formatedData;
		}
		
	}

}